#include "bsave.h"
#include <vector>
#include "stdlib.h"
#include <assert.h>

using std::cout;
using std::vector;

void SaveB(TreeGen3D *tree, int treenum, QString filename, Camera *cam){
    QFile *mout = new QFile(filename);
    mout->open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Append);
    QTextStream out(mout);

    if(treenum == 0)
        saveCameraData(out,cam);
    int nextIdx = 0;

    RecurSave(tree->treeRoot, out, -1, 1, nextIdx, treenum);

    mout->flush();
    mout->close();
    delete mout;
}

void saveCameraData(QTextStream &out, Camera *camera){
    out<<"c ";
    out << camera->eye.x << " ";
    out << camera->eye.y << " ";
    out << camera->eye.z << " ";
    out << camera->center.x << " ";
    out << camera->center.y << " ";
    out << camera->center.z << " ";
    out << camera->up.x << " ";
    out << camera->up.y << " ";
    out << camera->up.z << " ";
    out << camera->_angle << " ";
    out << camera->_near << " ";
    out << camera->_far << " ";
    out << camera->nUp.x << " ";
    out << camera->nUp.y << " ";
    out << camera->nUp.z << " ";
    out << camera->nCross.x << " ";
    out << camera->nCross.y << " ";
    out << camera->nCross.z << " ";
    out << camera->nLook.x << " ";
    out << camera->nLook.y << " ";
    out << camera->nLook.z << " ";
    out << endl;
}

void RecurSave(Bud *b, QTextStream &out, int parent, int term, int &nextIdx, int treenum){
    out<<"b "<< b->start.x <<" "<< b->start.y <<" "<<b->start.z <<" ";
    out<<b->end.x<<" "<<b->end.y<<" "<<b->end.z<<" ";
    out<<b->season<<" "<<b->term_fate<<" "<<b->aux_fate<<" "<<term<<" "<<parent<<" "<<treenum<<"\n";
    int me = nextIdx;
    nextIdx++;
    if(b->term)
        RecurSave(b->term, out, me, 1, nextIdx, treenum);
    if(b->aux)
        RecurSave(b->aux,out, me, 0, nextIdx, treenum);
}

TreeGen3D* LoadTree(QString filename, bool &success, bool &keeploading, int treenum){
    TreeGen3D *tree = new TreeGen3D();
    vector<Bud*> buds;
    assert(success);
    cout<<"bfile: "<<filename.toStdString()<<endl;
    QFile *in = new QFile(filename);
    in->open(QIODevice::ReadOnly | QIODevice::Text);
    QTextStream reader(in);
    QString next = reader.readLine();
    while(next.at(0).toAscii() == 'c'){
        next = reader.readLine();
    }
    //cout<<next.toStdString()<<endl;
    while(next != NULL){
        QStringList list = next.split(" ");
       // cout<<list.at(12).toInt()<<endl;
        //cout<<"tree num"<<treenum<<endl;
        if(list.at(12).toInt() == treenum){
            Bud *b = new Bud();
            if(list.at(0) != "b"){
                cout<<"load failed: a line did not start with b"<<endl;
                success = false;
                return NULL;
                in->close();
                delete in;
            }
            b->start = float3(list.at(1).toFloat(), list.at(2).toFloat(), list.at(3).toFloat());
            b->end = float3(list.at(4).toFloat(), list.at(5).toFloat(), list.at(6).toFloat());
            tree->initializeBud(b);

            b->season = list.at(7).toInt();
            b->term_fate = (Fate) list.at(8).toInt();
            b->aux_fate = (Fate) list.at(9).toInt();
            int isterm = list.at(10).toInt();
            int p = list.at(11).toInt();
    //        for(int i = 0; i<12; i++){
    //            cout<< i<<":  "<<list.at(i).toStdString()<<endl;
    //        }
            if(p == -1){
                tree->initializeBud(b);
                tree->treeRoot = b;
            }
            else{
                Bud *parent = buds.at(p);
                b->parent = parent;
                if(isterm == 1){
                    parent->term = b;
                }
                else if(isterm == 0){
                    parent->aux = b;
                }
                else{
                    cout<<"load failed: invalid term/aux line"<<endl;
                    success = false;
                    in->close();
                    delete in;
                    return NULL;
                }
            }
            buds.push_back(b);
        }
        else if(list.at(12).toInt() > treenum){
            cout<<"Loaded a tree successfully, continue loading"<<endl;
            in->close();
            delete in;
            keeploading = true;
            return tree;
        }
        next = reader.readLine();
    }

    in->close();
    delete in;
    cout<<"Successful Load"<<endl;
    keeploading = false;
    return tree;


}
